home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / lang / p_image1.sit / LSP Source / FileUnit.p < prev    next >
Encoding:
Text File  |  1989-07-29  |  61.2 KB  |  2,406 lines

  1. unit FileUnit;
  2.  
  3. {Routines used by the Image program for implementing File menu commands.}
  4.  
  5. interface
  6.  
  7.  
  8.     uses
  9.         QuickDraw, OSIntf, PickerIntf, PrintTraps, ToolIntf, globals, Utilities, Graphics;
  10.  
  11.  
  12.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  13.     procedure OpenFile (fname: str255; vnum: integer);
  14.     function OpenPict (fname: str255; vnum: integer; Reverting: boolean): boolean;
  15.     procedure SaveTiffAs (slines, sPixelsPerLine: integer; SavingSelection: boolean);
  16.     procedure SavePictAs (SavingSelection: boolean);
  17.     procedure SaveSelection (SaveAsSameType: boolean);
  18.     procedure SaveFile;
  19.     procedure GetFile;
  20.     procedure ImportFile;
  21.     procedure SavePalette;
  22.     procedure RevertToSaved;
  23.     procedure SaveSettings;
  24.     procedure GetInfo;
  25.     procedure SaveCameraWindow;
  26.     procedure SaveOutline;
  27.  
  28.     procedure DoPageSetup;
  29.     procedure Print (ShowDialog: boolean);
  30.     procedure SetHalftone;
  31.  
  32.  
  33.  
  34. implementation
  35.  
  36.     procedure TypeMismatch (fname: str255);
  37.         var
  38.             ignore: integer;
  39.     begin
  40.         ParamText('The file "', fname, '" is a different type, and therefore cannot be replaced', '');
  41.         InitCursor;
  42.         ignore := Alert(MessageID, nil);
  43.     end;
  44.  
  45.  
  46.     procedure SaveCustomClut (fname: str255; vnum: integer);
  47.         var
  48.             RefNum: integer;
  49.             err: OSErr;
  50.             MyColorTable: record
  51.                     ctSeed: LONGINT;
  52.                     transIndex: INTEGER;
  53.                     ctSize: INTEGER;
  54.                     ctTable: MyCSpecArray;
  55.                 end;
  56.             TempH: Handle;
  57.             Size: LongInt;
  58.     begin
  59.         err := SetVol(nil, vnum);
  60.         CreateResFile(fname);
  61.         refNum := OpenResFile(fname);
  62.         TempH := GetResource('clut', KlutzID);
  63.         if GetHandleSize(TempH) > 0 then
  64.             RmveResource(TempH);
  65.         size := SizeOF(MyColorTable);
  66.         TempH := NewHandle(size);
  67.         with MyColorTable do begin
  68.                 ctSeed := 0;
  69.                 TransIndex := 0;
  70.                 ctsize := 255;
  71.                 ctTable := info^.cTable;
  72.             end;
  73.         BlockMove(@MyColorTable, TempH^, size);
  74.         AddResource(TempH, 'clut', KLutzID, '');
  75.         WriteResource(TempH);
  76.         DisposHandle(TempH);
  77.         CloseResFile(refNum);
  78.     end;
  79.  
  80.  
  81.     function IOCheck (err: OSerr): integer;
  82.         var
  83.             ErrStr, Message: str255;
  84.             ignore: integer;
  85.     begin
  86.         if err <> 0 then begin
  87.                 Message := '';
  88.                 if err = -43 then
  89.                     Message := 'Disk Directory Full';
  90.                 if err = -34 then
  91.                     Message := 'Disk Full';
  92.                 NumToString(err, ErrStr);
  93.                 ParamText(Message, ErrStr, '', '');
  94.                 InitCursor;
  95.                 ignore := alert(IOErrorID, nil);
  96.             end;
  97.         IOCheck := err;
  98.     end;
  99.  
  100.  
  101.     procedure LookForCluts (fname: str255; vnum: integer);
  102.         var
  103.             RefNum: integer;
  104.             err: OSErr;
  105.             ok1, ok2: boolean;
  106.     begin
  107.         if not OptionKeyDown then begin
  108.                 err := SetVol(nil, vnum);
  109.                 refNum := OpenResFile(fname);
  110.                 if RefNum <> -1 then begin
  111.                         ok1 := LoadCLUTResource(KlutzID);
  112.                         if not ok1 then
  113.                             ok2 := LoadCLUTResource(PixelPaintID);
  114.                         CloseResFile(refNum);
  115.                     end;
  116.             end;
  117.     end;
  118.  
  119.  
  120.     procedure Swap2Bytes (var i: integer);
  121.         type
  122.             atype = packed array[1..2] of char;
  123.         var
  124.             a: atype;
  125.             c: char;
  126.     begin
  127.         a := atype(i);
  128.         c := a[1];
  129.         a[1] := a[2];
  130.         a[2] := c;
  131.         i := integer(a)
  132.     end;
  133.  
  134.  
  135.     procedure Swap4Bytes (var i: LongInt);
  136.         var
  137.             a: ostype;
  138.             c: char;
  139.     begin
  140.         a := ostype(i);
  141.         c := a[1];
  142.         a[1] := a[4];
  143.         a[4] := c;
  144.         c := a[2];
  145.         a[2] := a[3];
  146.         a[3] := c;
  147.         i := LongInt(a)
  148.     end;
  149.  
  150.  
  151.     procedure GetTiffEntry (f: integer; var tag: integer; var value: LongInt);
  152.         var
  153.             IFDEntry: TiffEntry;
  154.             ByteCount: LongInt;
  155.             IntValue: integer;
  156.             err: OSErr;
  157.     begin
  158.         ByteCount := 12;
  159.         err := FSRead(f, ByteCount, @IFDEntry);
  160.         with IFDEntry do begin
  161.                 tag := TagField;
  162.                 if IntelByteOrder then
  163.                     Swap2Bytes(tag);
  164.                 value := offset;
  165.                 if ftype = short then begin
  166.                         value := bsr(value, 16);
  167.                         if IntelByteOrder then begin
  168.                                 IntValue := value;
  169.                                 Swap2Bytes(IntValue);
  170.                                 value := IntValue
  171.                             end
  172.                     end
  173.                 else if IntelByteOrder then
  174.                     Swap4Bytes(value);
  175.   {dl(tag); dl(ftype); dl(length); dl(value); dnl;}
  176.             end;
  177.     end;
  178.  
  179.  
  180.     function OpenTiffHeader (f: integer): boolean;
  181.         var
  182.             TiffHeader: TiffHdr;
  183.             offset, ByteCount, length, ftype, value: LongInt;
  184.             err: OSErr;
  185.             nEntries, i, tag: integer;
  186.     begin
  187.         ByteCount := 8;
  188.         err := SetFPos(f, fsFromStart, 0);
  189.         err := fsread(f, ByteCount, @TiffHeader);
  190.         with TiffHeader do begin
  191.                 IntelByteOrder := ByteOrder = 'II';
  192.                 if (ByteOrder <> 'MM') and (ByteOrder <> 'II') then begin
  193.                         PutMessage('Invalid TIFF header.', '', '');
  194.                         OpenTiffHeader := false;
  195.                         exit(OpenTiffHeader)
  196.                     end;
  197.                 offset := FirstIFDOffset;
  198.                 if IntelByteOrder then
  199.                     Swap4Bytes(offset);
  200.                 err := SetFPos(f, fsFromStart, Offset);
  201.                 if IOCheck(err) <> NoErr then begin
  202.                         OpenTiffHeader := false;
  203.                         exit(OpenTiffHeader);
  204.                     end;
  205.                 ByteCount := 2;
  206.                 err := FSRead(f, ByteCount, @nEntries);
  207.                 if IntelByteOrder then
  208.                     Swap2Bytes(nEntries);
  209.                 with info^ do begin
  210.                         PixelsPerLine := 0;
  211.                         nLines := 0;
  212.                         offset := 0;
  213.                         for i := 1 to nEntries do begin
  214.                                 GetTiffEntry(f, tag, value);
  215.                                 if tag = 0 then begin
  216.                                         PutMessage('Invalid TIFF format.', '', '');
  217.                                         OpenTiffHeader := false;
  218.                                         exit(OpenTiffHeader)
  219.                                     end;
  220.                                 case tag of
  221.                                     ImageWidth: 
  222.                                         PixelsPerLine := value;
  223.                                     ImageLength: 
  224.                                         nLines := value;
  225.                                     BitsPerSample: 
  226.                                         begin
  227.                                             if value = 4 then
  228.                                                 PictureType := FourBitTiff;
  229.                                             if value = 1 then begin
  230.                                                     PutMessage('Image cannot open 1-bit TIFF files.', '', '');
  231.                                                     OpenTiffHeader := false;
  232.                                                     exit(OpenTiffHeader)
  233.                                                 end;
  234.                                         end;
  235.                                     Compression: 
  236.                                         if value <> 1 then begin
  237.                                                 PutMessage('Image cannot open compressed TIFF files.', '', '');
  238.                                                 OpenTiffHeader := false;
  239.                                                 exit(OpenTiffHeader)
  240.                                             end;
  241.                                     PhotoInterp: 
  242.                                         if (value = 1) and (PictureType <> FourBitTIFF) then
  243.                                             PictureType := InvertedTiff;
  244.                                     StripOffsets: 
  245.                                         ImageDataOffset := value;
  246.                                     RowsPerStrip: 
  247.                                         if value < nLines then begin
  248.                                                 PutMessage('Image cannot open TIFF files with multiple strips.', '', '');
  249.                                                 OpenTiffHeader := false;
  250.                                                 exit(OpenTiffHeader)
  251.                                             end;
  252.                                     ImageHdrTag: 
  253.                                         HeaderOffset := value;
  254.                                     otherwise
  255.                                 end;
  256.                             end; {for}
  257.                     end; {with}
  258.             end;
  259.         OpenTiffHeader := true;
  260.     end;
  261.  
  262.  
  263.     function OpenImageHeader (f: integer; fname: str255; vnum: integer): boolean;
  264.         var
  265.             ByteCount: LongInt;
  266.             err: OSErr;
  267.             TempHdr: PicHeader;
  268.             i, OldNExtra: integer;
  269.             ok: boolean;
  270.     begin
  271.         ByteCount := 512;
  272.         err := SetFPos(f, fsFromStart, info^.HeaderOffset);
  273.         err := fsread(f, ByteCount, @TempHdr);
  274.         if IOCheck(err) <> NoErr then begin
  275.                 OpenImageHeader := false;
  276.                 exit(OpenImageHeader);
  277.             end;
  278.         with info^, TempHdr do begin
  279.                 if PictureType <> TiffFile then begin
  280.                         nlines := hnlines;
  281.                         PixelsPerLine := hPixelsPerLine;
  282.                     end;
  283.                 if hversion > 54 then begin
  284.                         OldNExtra := nExtraColors;
  285.                         nExtraColors := hnExtraColors;
  286.                         ExtraColors := hExtraColors;
  287.                         if (nExtraColors > 0) or (OldNExtra <> nExtraColors) then
  288.                             RedrawCLUTWindow;
  289.                     end;
  290.                 if (hversion >= 42) and not OptionKeyDown then begin
  291.                         LUTMode := hLUTMode;
  292.                         case LUTMode of
  293.                             Colorpalette: 
  294.                                 begin
  295.                                     nColors := hncolors;
  296.                                     CheckColorWidth;
  297.                                     for i := 0 to ncolors - 1 do begin
  298.                                             RedX[i] := hr[i] * 255;
  299.                                             GreenX[i] := hg[i] * 255;
  300.                                             BlueX[i] := hb[i] * 255;
  301.                                         end;
  302.                                     ColorStart := hColorStart;
  303.                                     ColorWidth := hColorWidth;
  304.                                     UpdateColors;
  305.                                 end;
  306.                             AppleDefault: 
  307.                                 ok := LoadCLUTResource(AppleDefaultCLUT);
  308.                             Spectrum: 
  309.                                 Load256ColorCLUT;
  310.                             GrayScale: 
  311.                                 ResetGrayMap;
  312.                             Custom, CustomGrayscale: 
  313.                                 if PictureType <> PictFile then
  314.                                     LookForCluts(fname, vnum);
  315.                         end; {case}
  316.                         if hLutMode = CustomGrayscale then
  317.                             LutMode := CustomGrayscale;
  318.                     end;{if}
  319.                 if (hversion >= 65) and ((ForegroundColor <> hForegroundColor) or (BackgroundColor <> hBackgroundColor)) then begin
  320.                         SetForegroundColor(hForegroundColor);
  321.                         SetBackgroundColor(hBackgroundColor);
  322.                     end;
  323.                 if (hversion > 88) and (LUTMode = GrayScale) then begin
  324.                         p1x := hp1x;
  325.                         p1y := hp1y;
  326.                         p2x := hp2x;
  327.                         p2y := hp2y;
  328.                         SetGrayScaleLUT;
  329.                     end;
  330.                 if hversion > 106 then
  331.                     scale := hScale;
  332.                 units := hUnits;
  333.                 UnitsID := hUnitsID;
  334.                 if UnitsID = 0 then begin
  335.                         UnitsID := 7;
  336.                         units := 'mm';
  337.                     end;
  338.                 if hnCoefficients > 0 then begin
  339.                         fit := hfit;
  340.                         nCoefficients := hnCoefficients;
  341.                         Coefficient := hCoeff;
  342.                         UnitOfMeasure := hUM;
  343.                         Calibrated := true;
  344.                         GenerateValues;
  345.                     end
  346.                 else
  347.                     Calibrated := false;
  348.                 RestoringOutline := hContainsOutline;
  349.                 BinaryPic := hBinaryPic;
  350.                 OpenImageHeader := true
  351.             end;
  352.     end;
  353.  
  354.  
  355.     function OpenHeader (f: integer; fname: str255; vnum: integer): boolean;
  356.         var
  357.             ByteCount: LongInt;
  358.             hdr: packed array[1..512] of byte;
  359.             err: OSErr;
  360.             TempHdr: PicHeader;
  361.     begin
  362.         with info^ do begin
  363.                 if (WhatToOpen = OpenUnknown) or (WhatToOpen = OpenImported) then begin
  364.                         err := SetFPos(f, fsFromStart, 0);
  365.                         ByteCount := 8;
  366.                         err := fsread(f, ByteCount, @hdr);
  367.                         if ((hdr[1] = 73) and (hdr[2] = 73)) or ((hdr[1] = 77) and (hdr[2] = 77)) then
  368.                             WhatToOpen := OpenTIFF
  369.                         else if WhatToOpen = OpenUnknown then
  370.                             WhatToOpen := OpenImage
  371.                         else
  372.                             WhatToOpen := OpenMCID;
  373.                     end;
  374.                 case WhatToOpen of
  375.                     OpenImage: 
  376.                         begin
  377.                             err := SetFPos(f, fsFromStart, 0);
  378.                             ByteCount := 8;
  379.                             err := fsread(f, ByteCount, @TempHdr);
  380.                             if TempHdr.FileID = FileID8 then begin
  381.                                     HeaderOffset := 0;
  382.                                     PictureType := normal
  383.                                 end
  384.                             else begin
  385.                                     HeaderOffset := -1;
  386.                                     BlockMove(@TempHdr, @hdr, 8);
  387.                                     nlines := hdr[1] + hdr[2] * 256;
  388.                                     PixelsPerLine := hdr[3] + hdr[4] * 256;
  389.                                     PictureType := PDP11;
  390.                                 end;
  391.                             ImageDataOffset := 512;
  392.                         end;
  393.                     OpenMCID: 
  394.                         begin
  395.                             err := SetFPos(f, fsFromStart, 0);
  396.                             ByteCount := 4;
  397.                             err := fsread(f, ByteCount, @hdr);
  398.                             PixelsPerLine := hdr[1] + hdr[2] * 256 + 1;
  399.                             if PixelsPerLine > MaxPixelsPerLine then begin
  400.                                     beep;
  401.                                     PixelsPerLine := MaxPixelsPerLine;
  402.                                 end;
  403.                             nlines := hdr[3] + hdr[4] * 256 + 1;
  404.                             PictureType := imported;
  405.                             LUTMode := grayscale;
  406.                             HeaderOffset := -1;
  407.                             ImageDataOffset := 4;
  408.                         end;
  409.                     OpenCustom: 
  410.                         begin
  411.                             PixelsPerLine := ImportCustomWidth;
  412.                             nlines := ImportCustomHeight;
  413.                             PictureType := imported;
  414.                             HeaderOffset := -1;
  415.                             ImageDataOffset := ImportCustomOffset;
  416.                         end;
  417.                     OpenPICT2: 
  418.                         begin
  419.                             err := SetFPos(f, fsFromStart, 0);
  420.                             ByteCount := 8;
  421.                             err := fsread(f, ByteCount, @TempHdr);
  422.                             if TempHdr.FileID = FileID8 then
  423.                                 HeaderOffset := 0
  424.                             else
  425.                                 HeaderOffset := -1;
  426.                             PictureType := PictFile;
  427.                             LutMode := custom;
  428.                             ImageDataOffset := 512;
  429.                         end;
  430.                     OpenTIFF: 
  431.                         begin
  432.                             PictureType := TiffFile;
  433.                             ImageDataOffset := 0;
  434.                             HeaderOffset := -1;
  435.                             nlines := 100;
  436.                             PixelsPerLine := 100;
  437.                             if not OpenTiffHeader(f) then begin
  438.                                     OpenHeader := false;
  439.                                     exit(OpenHeader)
  440.                                 end;
  441.                             LutMode := Grayscale;
  442.                         end;
  443.                 end; {case}
  444.                 if HeaderOffset <> -1 then begin
  445.                         if not OpenImageHeader(f, fname, vnum) then begin
  446.                                 OpenHeader := false;
  447.                                 exit(OpenHeader)
  448.                             end
  449.                     end
  450.                 else
  451.                     calibrated := false;
  452.             end; {with}
  453.         OpenHeader := true;
  454.     end;
  455.  
  456.  
  457.     function SaveHeader (f, slines, sPixelsPerLine, vnum: integer; fname: str255; SavingSelection, SavingTIFF: boolean): OSErr;
  458.         var
  459.             TempHdr: PicHeader;
  460.             DummyHdr: array[1..128] of LongInt;
  461.             i: integer;
  462.             ByteCount: LongInt;
  463.             position: LongInt;
  464.             err: OSErr;
  465.             str: str255;
  466.     begin
  467.         with TempHdr, info^ do begin
  468.                 for i := 1 to 128 do
  469.                     DummyHdr[i] := 0;
  470.                 BlockMove(@DummyHdr, @TempHdr, HeaderSize);
  471.                 FileID := FileID8;
  472.                 hnlines := nlines;
  473.                 hPixelsPerLine := PixelsPerLine;
  474.                 hversion := version;
  475.                 hLUTMode := LUTMode;
  476.                 hnColors := ncolors;
  477.                 if LUTMode = ColorPalette then
  478.                     for i := 0 to nColors - 1 do begin
  479.                             hr[i] := BSR(RedX[i], 8);
  480.                             hg[i] := BSR(GreenX[i], 8);
  481.                             hb[i] := BSR(BlueX[i], 8);
  482.                         end;
  483.                 hColorStart := ColorStart;
  484.                 hColorWidth := ColorWidth;
  485.                 hnExtraColors := nExtraColors;
  486.                 hExtraColors := ExtraColors;
  487.                 hForegroundColor := ForegroundColor;
  488.                 hBackgroundColor := BackgroundColor;
  489.                 hScale := scale;
  490.                 hUnits[1] := units[1];
  491.                 hUnits[2] := units[2];
  492.                 hUnitsID := UnitsID;
  493.                 hp1x := p1x;
  494.                 hp1y := p1y;
  495.                 hp2x := p2x;
  496.                 hp2y := p2y;
  497.                 if nCoefficients > 0 then begin
  498.                         hfit := fit;
  499.                         hnCoefficients := nCoefficients;
  500.                         hCoeff := Coefficient;
  501.                         hUM := UnitOfMeasure;
  502.                     end;
  503.                 hContainsOutline := SavingOutline;
  504.                 hBinaryPic := BinaryPic;
  505.                 ByteCount := SizeOf(TempHdr);
  506.                 if ByteCount <> HeaderSize then begin
  507.                         NumToString(ByteCount, str);
  508.                         PutMessage('Internal error check: header size is incorrect.  Size=', str, '');
  509.                         ExitToShell;
  510.                     end;
  511.                 if SavingSelection then begin
  512.                         hnlines := slines;
  513.                         hPixelsPerLine := sPixelsPerLine;
  514.                     end;
  515.                 err := fswrite(f, ByteCount, @TempHdr);
  516.                 SaveHeader := IOCheck(err);
  517.                 if ((LutMode = Custom) or (LutMode = CustomGrayscale)) and SavingTIFF then
  518.                     SaveCustomClut(fname, vnum);
  519.             end; {with}
  520.     end;
  521.  
  522.  
  523.     function SaveTiffDirectory (f, slines, sPixelsPerLine: integer; SavingSelection: boolean): OSErr;
  524.         var
  525.             err: integer;
  526.             ByteCount, width, height: LongInt;
  527.     begin
  528.         with info^ do begin
  529.                 if SavingSelection then begin
  530.                         width := sPixelsPerLine;
  531.                         height := sLines
  532.                     end
  533.                 else begin
  534.                         width := PixelsPerLine;
  535.                         height := nLines
  536.                     end;
  537.                 with TiffInfo do begin
  538.                         directory[2].offset := bsl(width, 16);
  539.                         directory[3].offset := bsl(height, 16);
  540.                     end;
  541.             end;
  542.         ByteCount := SizeOf(TiffInfo);
  543.         err := SetFPos(f, FSFromStart, 0);
  544.         err := FSWrite(f, ByteCount, @TiffInfo);
  545.         SaveTiffDirectory := IOCheck(err);
  546.     end;
  547.  
  548.  
  549.     function SaveTiffFile (fname: str255; vnum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  550.         var
  551.             f, err, i: integer;
  552.             HdrSize, ByteCount, SelectionSize: LongInt;
  553.             TheInfo: FInfo;
  554.     begin
  555.         SaveTiffFile := false;
  556.         if Info = NoInfo then begin
  557.                 beep;
  558.                 exit(SaveTiffFile)
  559.             end;
  560.         ShowWatch;
  561.         err := fsopen(fname, vNum, f);
  562.         if IOCheck(err) <> 0 then
  563.             exit(SaveTiffFile);
  564.         with Info^ do begin
  565.                 if SaveTiffDirectory(f, slines, sPixelsPerLine, SavingSelection) <> NoErr then begin
  566.                         err := fsclose(f);
  567.                         err := FSDelete(fname, vnum);
  568.                         exit(SaveTiffFile)
  569.                     end;
  570.                 err := SetFPos(f, FSFromStart, TiffDirSize);
  571.                 if SaveHeader(f, slines, sPixelsPerLine, vnum, fname, SavingSelection, true) <> NoErr then begin
  572.                         err := fsclose(f);
  573.                         err := FSDelete(fname, vnum);
  574.                         exit(SaveTiffFile)
  575.                     end;
  576.                 if SavingSelection then begin
  577.                         SelectionSize := LongInt(slines) * sPixelsPerLine;
  578.                         ByteCount := SelectionSize;
  579.                         err := fswrite(f, ByteCount, UndoBuf)
  580.                     end
  581.                 else begin
  582.                         ByteCount := PicSize;
  583.                         err := fswrite(f, ByteCount, PicBaseAddr);
  584.                         SelectionSize := 0
  585.                     end;
  586.                 if IOCheck(err) <> 0 then begin
  587.                         err := fsclose(f);
  588.                         err := FSDelete(fname, vnum);
  589.                         exit(SaveTiffFile)
  590.                     end;
  591.                 HdrSize := HeaderSize + TiffDirSize;
  592.                 if SavingSelection then
  593.                     err := SetEOF(f, SelectionSize + HdrSize)
  594.                 else
  595.                     err := SetEOF(f, PicSize + HdrSize);
  596.                 err := fsclose(f);
  597.                 err := GetFInfo(fname, vnum, TheInfo);
  598.                 if TheInfo.fdCreator <> 'IMAG' then begin
  599.                         TheInfo.fdCreator := 'IMAG';
  600.                         err := SetFInfo(fname, vnum, TheInfo);
  601.                     end;
  602.                 if TheInfo.fdType <> 'TIFF' then begin
  603.                         TheInfo.fdType := 'TIFF';
  604.                         err := SetFInfo(fname, vnum, TheInfo);
  605.                     end;
  606.                 err := FlushVol(nil, vNum);
  607.                 if not SavingSelection then begin
  608.                         if (PictureType <> Camera) and (PictureType <> BlankField) then begin
  609.                                 PictureType := normal;
  610.                                 SetWTitle(wptr, fname);
  611.                                 title := fname;
  612.                                 vref := vnum;
  613.                             end;
  614.                     end;
  615.                 Changes := false;
  616.             end; {with}
  617.         SaveTiffFile := true;
  618.     end;
  619.  
  620.  
  621.     procedure UpdateWindowsMenuItem (PicSize: LongInt; title: str255; PicNum: integer);
  622.         var
  623.             str: str255;
  624.     begin
  625.         if PicNum <= MaxPicsInMenu then begin
  626.                 NumToString(PicSize div 1024, str);
  627.                 str := concat(title, '  ', str, 'K');
  628.                 SetItem(WindowsMenuH, PicNum + nItems, str);
  629.             end;
  630.     end;
  631.  
  632.  
  633.     procedure SaveTiffAs;{(slines,sPixelsPerLine:integer; SavingSelection:boolean)}
  634.         var
  635.             err: integer;
  636.             where: Point;
  637.             reply: SFReply;
  638.             TheInfo: FInfo;
  639.             replacing, ok: boolean;
  640.             name: str255;
  641.     begin
  642.         if Info = NoInfo then begin
  643.                 beep;
  644.                 exit(SaveTiffAs)
  645.             end;
  646.         where.v := 50;
  647.         where.h := 50;
  648.         name := info^.title;
  649.         if name = 'Camera' then
  650.             name := 'Untitled';
  651.         SFPutFile(Where, 'Save as?', name, nil, reply);
  652.         if not reply.good then
  653.             exit(SaveTiffAs);
  654.         err := GetFInfo(reply.fname, reply.vRefNum, TheInfo);
  655.         case err of
  656.             NoErr: 
  657.                 with TheInfo do begin
  658.                         if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'IPIC') then begin
  659.                                 TypeMismatch(reply.fname);
  660.                                 exit(SaveTiffAs)
  661.                             end;
  662.                         replacing := true;
  663.                     end;
  664.             FNFerr: 
  665.                 begin
  666.                     err := create(reply.fname, reply.vRefNum, 'IMAG', 'TIFF');
  667.                     if IOCheck(err) <> 0 then
  668.                         exit(SaveTiffAs);
  669.                     replacing := false;
  670.                 end;
  671.             otherwise
  672.                 if IOCheck(err) <> 0 then
  673.                     exit(SaveTiffAs);
  674.         end;
  675.         ok := SaveTiffFile(reply.fname, reply.vRefNum, slines, sPixelsPerLine, SavingSelection);
  676.         if ok then
  677.             with info^ do
  678.                 UpdateWindowsMenuItem(PicSize, title, PicNum);
  679.         with info^ do
  680.             if SavingSelection and Replacing and (PictureType <> Camera) and (PictureType <> BlankField) then
  681.                 PictureType := Leftover;
  682.     end;
  683.  
  684.  
  685.     function SavePICTFile (fname: str255; vnum: integer; SavingSelection: boolean): boolean;
  686.         var
  687.             f, err, i, v: integer;
  688.             ByteCount, PICTSize: LongInt;
  689.             PicH: PicHandle;
  690.             fRect, frect2: rect;
  691.             tPort: GrafPtr;
  692.             TheInfo: FInfo;
  693.     begin
  694.         if OpPending then
  695.             KillRoi;
  696.         SavePICTFile := false;
  697.         ShowWatch;
  698.         err := fsopen(fname, vnum, f);
  699.         err := SetFPos(f, FSFromStart, 0);
  700.         if SaveHeader(f, 0, 0, vnum, fname, SavingSelection, false) <> 0 then begin
  701.                 err := fsclose(f);
  702.                 err := FSDelete(fname, vnum);
  703.                 exit(SavePICTFile)
  704.             end;
  705.         with info^ do begin
  706.                 GetPort(tPort);
  707.                 if SavingSelection then
  708.                     fRect := osRoiRect
  709.                 else
  710.                     SetRect(fRect, 0, 0, PixelsPerLine, nlines);
  711.                 with frect do
  712.                     SetRect(frect2, 0, 0, right - left, bottom - top);
  713.                 with osPort^ do begin
  714.                         SetPort(GrafPtr(osPort));
  715.                         ClipRect(PicRect);
  716.                         LoadLUT(info^.cTable);  {Restore look-up table in case it has changed.}
  717.                         PicH := OpenPicture(fRect2);
  718.                         if SavingOutline then begin
  719.                                 PenNormal;
  720.                                 FrameRgn(info^.osroiRgn);
  721.                                 SavingOutline := false
  722.                             end
  723.                         else begin
  724.                                 hlock(handle(PortPixMap));
  725.                                 CopyBits(BitMapHandle(PortPixMap)^^, BitMapHandle(PortPixMap)^^, frect, frect2, SrcCopy, nil);
  726.                                 hunlock(handle(PortPixMap));
  727.                             end;
  728.                         ClosePicture;
  729.                     end;
  730.                 SetPort(tPort);
  731.                 PICTSize := GetHandleSize(handle(PicH));
  732.                 if PICTSize <= 0 then begin
  733.                         err := fsclose(f);
  734.                         err := FSDelete(fname, vnum);
  735.                         exit(SavePICTFile)
  736.                     end;
  737.                 err := fswrite(f, PICTSize, pointer(PicH^));
  738.                 if IOCheck(err) <> 0 then begin
  739.                         err := fsclose(f);
  740.                         err := FSDelete(fname, vnum);
  741.                         exit(SavePICTFile)
  742.                     end;
  743.                 DisposHandle(handle(PicH));
  744.                 ByteCount := PICTSize + HeaderSize;
  745.                 err := SetEOF(f, ByteCount);
  746.                 err := fsclose(f);
  747.                 err := GetFInfo(fname, vnum, TheInfo);
  748.                 if TheInfo.fdCreator <> 'IMAG' then begin
  749.                         TheInfo.fdCreator := 'IMAG';
  750.                         err := SetFInfo(fname, vnum, TheInfo);
  751.                     end;
  752.                 if TheInfo.fdType <> 'PICT' then begin
  753.                         TheInfo.fdType := 'PICT';
  754.                         err := SetFInfo(fname, vnum, TheInfo);
  755.                     end;
  756.                 err := FlushVol(nil, vnum);
  757.                 if not SavingSelection then begin
  758.                         if (PictureType <> Camera) and (PictureType <> BlankField) then begin
  759.                                 PictureType := PictFile;
  760.                                 SetWTitle(wptr, fname);
  761.                                 title := fname;
  762.                                 vref := vnum;
  763.                             end;
  764.                         Changes := false;
  765.                     end;
  766.             end; {with}
  767.         SavePICTFile := true;
  768.     end;
  769.  
  770.  
  771.     procedure SaveFile;
  772.         var
  773.             fname: str255;
  774.             size: LongInt;
  775.             ok: boolean;
  776.     begin
  777.         if Info = NoInfo then begin
  778.                 beep;
  779.                 exit(SaveFile)
  780.             end;
  781.         if OpPending then
  782.             KillRoi;
  783.         with Info^ do begin
  784.                 GetWTitle(wptr, fname);
  785.                 size := 0;
  786.                 if PictureType = TiffFile then
  787.                     ok := SaveTiffFile(fname, vref, 0, 0, false)
  788.                 else if PictureType = PictFile then
  789.                     ok := SavePICTFile(fname, vref, false)
  790.                 else
  791.                     SaveTiffAs(0, 0, false);
  792.             end;
  793.     end;
  794.  
  795.  
  796.     procedure SavePICTAs;{(SavingSelection:boolean)}
  797.         var
  798.             f, err, i: integer;
  799.             where: Point;
  800.             reply: SFReply;
  801.             TheInfo: FInfo;
  802.             replacing, ok: boolean;
  803.             name: str255;
  804.     begin
  805.         if info = NoInfo then begin
  806.                 beep;
  807.                 exit(SavePictAs)
  808.             end;
  809.         where.v := 50;
  810.         where.h := 50;
  811.         name := info^.title;
  812.         if name = 'Camera' then
  813.             name := 'Untitled';
  814.         SFPutFile(Where, 'Save as?', name, nil, reply);
  815.         if not reply.good then
  816.             exit(SavePictAs);
  817.         err := GetFInfo(reply.fname, reply.vRefNum, TheInfo);
  818.         case err of
  819.             NoErr: 
  820.                 with TheInfo do begin
  821.                         if (fdType <> 'TIFF') and (fdType <> 'PICT') and (fdType <> 'IPIC') then begin
  822.                                 TypeMismatch(reply.fname);
  823.                                 exit(SavePictAs)
  824.                             end;
  825.                         replacing := true;
  826.                     end;
  827.             FNFerr: 
  828.                 begin
  829.                     err := create(reply.fname, reply.vRefNum, 'IMAG', 'PICT');
  830.                     if IOCheck(err) <> 0 then
  831.                         exit(SavePictAs);
  832.                     replacing := false;
  833.                 end;
  834.             otherwise
  835.                 if IOCheck(err) <> 0 then
  836.                     exit(SavePictAs);
  837.         end;
  838.         ok := SavePICTFile(reply.fname, reply.vRefNum, SavingSelection);
  839.         if ok then
  840.             with info^ do
  841.                 UpdateWindowsMenuItem(PicSize, title, PicNum);
  842.         with info^ do
  843.             if SavingSelection and replacing and (PictureType <> Camera) and (PictureType <> BlankField) then
  844.                 PictureType := Leftover;
  845.     end;
  846.  
  847.  
  848.     procedure SaveSelection;{(SaveAsSameType:boolean)}
  849.         var
  850.             size, offset: LongInt;
  851.             i, slines, spixelsPerLine, hstart, vstart: integer;
  852.             src, dst: ptr;
  853.     begin
  854.         if NoSelection or NotRectangular or NotInBounds then
  855.             exit(SaveSelection);
  856.         if OpPending then
  857.             KillRoi;
  858.         with info^ do begin
  859.                 with osRoiRect do begin
  860.                         sPixelsPerLine := right - left;
  861.                         if odd(sPixelsPerLine) and (left + sPixelsPerLine < PicRect.right) then
  862.                             sPixelsPerLine := sPixelsPerLine + 1;
  863.                         slines := bottom - top;
  864.                         size := LongInt(slines) * sPixelsPerLine;
  865.                         hstart := left;
  866.                         vstart := top;
  867.                     end;
  868.                 if (PictureType <> PictFile) or not SaveAsSameType then begin
  869.                         if size > UndoBufSize then begin
  870.                                 PutMessage('There is not enough memory available to save the selection', '', '');
  871.                                 exit(SaveSelection)
  872.                             end;
  873.                         offset := LongInt(vstart) * BytesPerRow + hstart;
  874.                         src := ptr(ord4(PicBaseAddr) + offset);
  875.                         dst := UndoBuf;
  876.                         for i := 0 to slines - 1 do begin
  877.                                 BlockMove(src, dst, sPixelsPerLine);
  878.                                 src := ptr(ord4(src) + BytesPerRow);
  879.                                 dst := ptr(ord4(dst) + sPixelsPerLine);
  880.                             end;
  881.                     end;
  882.                 if (PictureType = PictFile) and SaveAsSameType then
  883.                     SavePICTAs(true)
  884.                 else
  885.                     SaveTiffAs(slines, sPixelsPerLine, true);
  886.             end;
  887.     end;
  888.  
  889.  
  890.     procedure SaveCameraWindow;
  891.     begin
  892.         SelectAll(true);
  893.         SaveSelection(false);
  894.         KillRoi;
  895.         info^.changes := false
  896.     end;
  897.  
  898.  
  899.     function SaveChanges: integer;
  900.         const
  901.             yesID = 1;
  902.             noID = 2;
  903.             cancelID = 3;
  904.         var
  905.             id: integer;
  906.     begin
  907.         id := 0;
  908.         if info^.changes then
  909.             with info^ do begin
  910.                     ParamText(title, '', '', '');
  911.                     InitCursor;
  912.                     id := alert(600, nil);
  913.                     if id = yesID then begin
  914.                             if info^.PictureType <> Camera then
  915.                                 SaveFile
  916.                             else begin
  917.                                     SelectAll(false);
  918.                                     SaveSelection(true);
  919.                                     changes := false
  920.                                 end;
  921.                             InitCursor;
  922.                         end;
  923.                 end;
  924.         if (id = cancelID) or ((id = yesID) and (info^.changes)) then
  925.             SaveChanges := cancel
  926.         else
  927.             SaveChanges := ok;
  928.     end;
  929.  
  930.  
  931.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  932.         var
  933.             i, kind, n: integer;
  934.             TempInfo: InfoPtr;
  935.             SizeStr, str: str255;
  936.             wp: ^WindowPtr;
  937.     begin
  938.         kind := WindowPeek(WhichWindow)^.WindowKind;
  939.         CloseAWindow := ok;
  940.         case kind of
  941.             PicKind: 
  942.                 with Info^ do begin
  943.                         Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  944.                         if SaveChanges = cancel then begin
  945.                                 CloseAWindow := cancel;
  946.                                 exit(CloseAWindow)
  947.                             end;
  948.                         if PicNum <= MaxPicsInMenu then
  949.                             DelMenuItem(WindowsMenuH, PicNum + nItems);
  950.                         for i := PicNum to nPics - 1 do begin
  951.                                 PicWindow[i] := PicWindow[i + 1];
  952.                                 TempInfo := pointer(WindowPeek(PicWindow[i])^.RefCon);
  953.                                 TempInfo^.PicNum := i
  954.                             end;
  955.                         if (PicNum <= MaxPicsInMenu) and (nPics > MaxPicsInMenu) then begin
  956.                                 TempInfo := pointer(WindowPeek(PicWindow[MaxPicsInMenu])^.RefCon);
  957.                                 with TempInfo^ do begin
  958.                                         NumToString(PicSize div 1024, SizeStr);
  959.                                         str := concat(title, '  ', SizeStr, 'K');
  960.                                         AppendMenu(WindowsMenuH, ' ');
  961.                                         InsertMenu(WindowsMenuH, 0);
  962.                                     end;
  963.                             end;
  964.                         if PictureType = camera then
  965.                             CameraInfo := nil
  966.                         else
  967.                             DisposPtr(PicBaseAddr);
  968.                         if PictureType = BlankField then
  969.                             BlankFieldInfo := nil;
  970.                         if PictureType = DebugWindow then
  971.                             DebugInfo := nil;
  972.                         if PictureType = ScionType then
  973.                             ScionInfo := nil;
  974.                         DisposeWindow(WhichWindow);
  975.                         CloseCPort(osPort);
  976.                         Dispose(osPort);
  977.                         DisposeRgn(osroiRgn);
  978.                         nPics := nPics - 1;
  979.                         OpPending := false;
  980.                         DisposPtr(pointer(Info));
  981.                         Info := NoInfo;
  982.                         if (nPics = 0) and (not finished) then
  983.                             with info^ do begin
  984.                                     LoadLUT(info^.cTable);
  985.                                     if (LutMode = GrayScale) or (LutMode = CustomGrayScale) then
  986.                                         DrawGrayMap;
  987.                                 end;
  988.                     end;
  989.             HistoKind: 
  990.                 begin
  991.                     DisposeWindow(HistoWindow);
  992.                     HistoWindow := nil;
  993.                     ContinuousHistogram := false;
  994.                     SetMenuItem(GetMHandle(WindowsMenu), 7, false);
  995.                 end;
  996.             ProfilePlotKind, CalibrationPlotKind: 
  997.                 begin
  998.                     DisposeWindow(PlotWindow);
  999.                     PlotWindow := nil;
  1000.                     KillPicture(PlotPICT);
  1001.                     PlotPICT := nil;
  1002.                     SetMenuItem(GetMHandle(WindowsMenu), 8, false);
  1003.                 end;
  1004.             PasteControlKind: 
  1005.                 begin
  1006.                     DisposeWindow(PasteControl);
  1007.                     PasteControl := nil;
  1008.                     wp := pointer(GhostWindow);
  1009.                     wp^ := nil;
  1010.                     SetMenuItem(GetMHandle(WindowsMenu), 9, false);
  1011.                 end;
  1012.         end; {case}
  1013.     end;
  1014.  
  1015.  
  1016.     procedure Read4BitTIFF (f: integer);
  1017.         var
  1018.             vloc, hloc, i: integer;
  1019.             ByteCount, count: LongInt;
  1020.             err: OSErr;
  1021.             UnpackedLine, PackedLine: LineType;
  1022.     begin
  1023.         with info^ do begin
  1024.                 if PixelsPerLine > MaxPixelsPerLine then
  1025.                     exit(Read4BitTIFF);
  1026.                 ByteCount := (PixelsPerLine + 1) div 2;
  1027.                 for vloc := 0 to nLines - 1 do begin
  1028.                         err := FSRead(f, ByteCount, @PackedLine);
  1029.                         i := 0;
  1030.                         for hloc := 0 to PixelsPerLine - 1 do
  1031.                             if odd(hloc) then begin
  1032.                                     UnpackedLine[hloc] := bsl(band(PackedLine[i], $F), 4);
  1033.                                     i := i + 1;
  1034.                                 end
  1035.                             else
  1036.                                 UnpackedLine[hloc] := band(PackedLine[i], $F0);
  1037.                         PutLine(0, vloc, PixelsPerLine, UnpackedLine);
  1038.                     end;
  1039.             end; {with}
  1040.     end;
  1041.  
  1042.  
  1043.     procedure OpenFile;{(fname:str255; vnum:integer)}
  1044.         var
  1045.             ticks, ByteCount, i: LongInt;
  1046.             err: OSErr;
  1047.             f: integer;
  1048.             line, pixel: integer;
  1049.             r2, r3: rect;
  1050.             p: ptr;
  1051.             value: byte;
  1052.             iptr: ptr;
  1053.     begin
  1054.         ShowWatch;
  1055.         err := fsopen(fname, vNum, f);
  1056.         SaveInfo := Info;
  1057.         iptr := NewPtr(SizeOf(PicInfo));
  1058.         if iptr = nil then begin
  1059.                 PutOutOfMemMsg;
  1060.                 DisposPtr(iptr);
  1061.                 err := fsclose(f);
  1062.                 exit(OpenFile)
  1063.             end;
  1064.         Info := pointer(iptr);
  1065.         info^ := SaveInfo^;
  1066.         with Info^ do begin
  1067.                 if not OpenHeader(f, fname, vnum) then begin
  1068.                         DisposPtr(iptr);
  1069.                         err := fsclose(f);
  1070.                         Info := SaveInfo;
  1071.                         exit(OpenFile)
  1072.                     end;
  1073.                 PicSize := LongInt(nlines) * PixelsPerLine;
  1074.                 PicBaseAddr := Getmemory(PicSize);
  1075.                 if PicBaseAddr = nil then begin
  1076.                         err := fsclose(f);
  1077.                         exit(OpenFile)
  1078.                     end;
  1079.                 MakeNewWindow(fname);
  1080.                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  1081.                 if PictureType = FourBitTIFF then
  1082.                     Read4BitTIFF(f)
  1083.                 else
  1084.                     err := fsread(f, PicSize, PicBaseAddr);
  1085.                 if (PictureType = pdp11) or (PictureType = imported) or (PictureType = InvertedTIFF) then
  1086.                     InvertPic;
  1087.                 if PictureType = FourBitTIFF then
  1088.                     PictureType := imported;
  1089.     {Picture will be copied to the screen by DoUpdate}
  1090.                 vref := vnum;
  1091.                 if PicSize > UndoBufSize then
  1092.                     PutWarning;
  1093.             end; {with}
  1094.         err := fsclose(f);
  1095.         SetupUndo;
  1096.     end;
  1097.  
  1098.  
  1099.     procedure InitPictBuffer (howBig: LongInt);
  1100.     begin
  1101.         repeat
  1102.             PictBuffer := NewPtr(howBig);
  1103.             if PictBuffer = nil then
  1104.                 howBig := howBig div 2;
  1105.         until PictBuffer <> nil;
  1106.         DisposPtr(PictBuffer);
  1107.         PictBuffer := NewPtr(howBig div 2);
  1108.     end;
  1109.  
  1110.  
  1111.     procedure FillPictBuffer;
  1112.         var
  1113.             count: LongInt;
  1114.             err: OSErr;
  1115.     begin
  1116.         count := GetPtrSize(PictBuffer);
  1117.         if not fitsInPictBuffer then
  1118.             err := FSRead(PictF, count, PictBuffer);
  1119.         bytesInPictBuffer := count;
  1120.         curPictBufPtr := PictBuffer;
  1121.     end;
  1122.  
  1123.  
  1124.     procedure GetPICTData (dataPtr: Ptr; byteCount: Integer);
  1125.     {Input picture spooler routine taken from Apple's PICTViewer example program.}
  1126.         var
  1127.             count: LongInt;
  1128.             anErr: OSErr;
  1129.     begin
  1130.         count := byteCount;
  1131.         repeat
  1132.             if bytesInPictBuffer >= count then begin
  1133.                     BlockMove(curPictBufPtr, dataPtr, count);
  1134.                     curPictBufPtr := Ptr(Ord4(curPictBufPtr) + count);
  1135.                     bytesInPictBuffer := bytesInPictBuffer - count;
  1136.                     count := 0;
  1137.                 end
  1138.             else begin        {Not enough in buffer}
  1139.                     if bytesInPictBuffer > 0 then begin
  1140.                             BlockMove(curPictBufPtr, dataPtr, bytesInPictBuffer);
  1141.                             dataPtr := Ptr(Ord4(dataPtr) + bytesInPictBuffer);
  1142.                             count := count - bytesInPictBuffer;
  1143.                         end;
  1144.                     FillPictBuffer;
  1145.                 end;
  1146.         until count = 0;
  1147.     end;
  1148.  
  1149.  
  1150.     procedure BitInfo (var srcBits: PixMap; var srcRect, dstRect: rect; mode: integer; maskRgn: rgnHandle);
  1151.         var
  1152.             i, size: integer;
  1153.     begin
  1154.         if BitInfoCount = 0 then
  1155.             if srcBits.rowBytes < 0 then
  1156.                 with srcBits.pmTable^^ do begin{Make sure it is a PixMap.}
  1157.                         size := ctSize;
  1158.                         if size > 255 then
  1159.                             size := 255;
  1160.                         if size > 0 then
  1161.                             BitInfoCount := BitInfoCount + 1;
  1162.                         for i := 0 to size do
  1163.                             info^.cTable[i].rgb := ctTable[i].rgb;
  1164.                         if size > 0 then
  1165.                             info^.LutMode := custom;
  1166.                     end;
  1167.     end;
  1168.  
  1169.  
  1170.     procedure GetClutFromPict (thePict: PicHandle);
  1171.   {Refer to "Screen Dump FKEY for Color Picts", February 1988 MacTutor.}
  1172.         type
  1173.             myPicData = record
  1174.                     p: Picture;
  1175.                     ID: integer
  1176.                 end;
  1177.             myPicPtr = ^myPicData;
  1178.             myPicHdl = ^myPicPtr;
  1179.         var
  1180.             tempProcs: CQDProcs;
  1181.             SaveProcsPtr: QDProcsPtr;
  1182.             tPort: GrafPtr;
  1183.             err: osErr;
  1184.     begin
  1185.         with info^ do begin
  1186.                 GetPort(tPort);
  1187.                 SetPort(wptr);
  1188.                 SaveProcsPtr := pointer(wptr^.grafProcs);
  1189.                 SetStdCProcs(tempProcs);
  1190.                 tempProcs.bitsProc := @BitInfo;
  1191.                 tempProcs.getPicProc := @GetPICTData;
  1192.                 BitInfoCount := 0;
  1193.                 wptr^.grafProcs := @tempProcs;
  1194.                 err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  1195.                 FillPictBuffer;
  1196.                 DrawPicture(thePict, thePict^^.picFrame);
  1197.                 SetPort(tPort);
  1198.                 wptr^.grafProcs := pointer(SaveProcsPtr);
  1199.             end;
  1200.         LoadLUT(info^.cTable);
  1201.     end;
  1202.  
  1203.  
  1204.     function isGrayScaleCLUT: boolean;
  1205.         var
  1206.             i: integer;
  1207.             GrayScaleCLUT: boolean;
  1208.     begin
  1209.         GrayscaleClut := true;
  1210.         i := 0;
  1211.         repeat
  1212.             with info^.cTable[i].rgb do
  1213.                 GrayscaleClut := GrayscaleClut and (red = green) and (green = blue);
  1214.             i := i + 1;
  1215.         until (i = 256) or not GrayscaleClut;
  1216.         isGrayScaleClut := GrayScaleCLUT;
  1217.     end;
  1218.  
  1219.  
  1220.     procedure RestoreOutline (thePict: PicHandle; pRect: rect);
  1221.         var
  1222.             tRect: rect;
  1223.             temp: integer;
  1224.             TempRgn: RgnHandle;
  1225.     begin
  1226.         with info^ do begin
  1227.                 RoiShowing := true;
  1228.                 PenNormal;
  1229.                 OpenRgn;
  1230.                 DrawPicture(thePict, pRect);
  1231.                 CloseRgn(osroiRgn);
  1232.                 if GetHandleSize(handle(osroiRgn)) = 10 then
  1233.                     roiType := RectRoi
  1234.                 else
  1235.                     roiType := RgnRoi;
  1236.                 osroiRect := osroiRgn^^.rgnBBox;
  1237.                 roiRect := osroiRect;
  1238.                 OffscreenToScreenRect(roiRect);
  1239.                 RestoringOutline := false;
  1240.             end;
  1241.     end;
  1242.  
  1243.  
  1244.     function OpenPict;{(fname:str255; vnum:integer; Reverting:boolean):boolean}
  1245.         var
  1246.             err: OSErr;
  1247.             i: integer;
  1248.             value: byte;
  1249.             iptr: ptr;
  1250.             PictSize, HowBig: LongInt;
  1251.             thePict: PicHandle;
  1252.             tPort: GrafPtr;
  1253.             tempProcs: CQDProcs;
  1254.             SaveProcsPtr: QDProcsPtr;
  1255.  
  1256.         procedure Abort;
  1257.         begin
  1258.             if not reverting then begin
  1259.                     DisposPtr(pointer(Info));
  1260.                     Info := SaveInfo;
  1261.                     LoadLUT(info^.cTable);
  1262.                 end;
  1263.             if thePict <> nil then
  1264.                 DisposHandle(handle(thePict));
  1265.             if PictF <> 0 then
  1266.                 err := fsclose(PictF);
  1267.             RestoringOutline := false;
  1268.             exit(OpenPict);
  1269.         end;
  1270.  
  1271.     begin
  1272.         PictF := 0;
  1273.         thePict := nil;
  1274.         OpenPict := false;
  1275.         ShowWatch;
  1276.         SaveInfo := Info;
  1277.         err := fsopen(fname, vNum, PictF);
  1278.         if IOCheck(err) <> 0 then
  1279.             Abort;
  1280.         if not Reverting then begin
  1281.                 iptr := NewPtr(SizeOf(PicInfo));
  1282.                 if iptr = nil then begin
  1283.                         PutOutOfMemMsg;
  1284.                         DisposPtr(iptr);
  1285.                         err := fsclose(PictF);
  1286.                         exit(OpenPict)
  1287.                     end;
  1288.                 Info := pointer(iptr);
  1289.                 info^ := SaveInfo^;
  1290.             end;
  1291.         with Info^ do begin
  1292.                 err := GetEof(PictF, PictSize);
  1293.                 if IOCheck(err) <> 0 then
  1294.                     Abort;
  1295.                 PictSize := PictSize - 512;
  1296.                 if PictSize <= 0 then
  1297.                     Abort;
  1298.                 WhatToOpen := OpenPICT2;
  1299.                 if not OpenHeader(PictF, fname, vnum) then
  1300.                     Abort;
  1301.                 thePict := PicHandle(NewHandle(SizeOf(Picture)));
  1302.                 if thePict = nil then
  1303.                     Abort;
  1304.                 err := SetFPos(PictF, fsFromStart, 512);
  1305.                 if IOCheck(err) <> 0 then
  1306.                     Abort;
  1307.                 howBig := SizeOf(Picture);
  1308.                 err := FSRead(PictF, howBig, Pointer(thePict^));
  1309.                 with thePict^^.PicFrame do begin
  1310.                         nlines := bottom - top;
  1311.                         PixelsPerLine := right - left;
  1312.                     end;
  1313.                 PicSize := LongInt(nlines) * PixelsPerLine;
  1314.                 if not Reverting then begin
  1315.                         PicBaseAddr := GetMemory(PicSize);
  1316.                         if PicBaseAddr = nil then begin
  1317.                                 DisposHandle(handle(thePict));
  1318.                                 err := fsclose(PictF);
  1319.                                 exit(OpenPict)
  1320.                             end;
  1321.                         MakeNewWindow(fname);
  1322.                     end;
  1323.                 if (PicSize > UndoBufSize) and (not Reverting) then begin
  1324.                         PutWarning;
  1325.                         ShowWatch;
  1326.                     end;
  1327.                 err := GetEof(PictF, howBig);
  1328.                 howBig := howBig - (512 + SizeOf(Picture));
  1329.                 InitPictBuffer(HowBig * 2);
  1330.                 if GetPtrSize(PictBuffer) >= howBig then begin
  1331.                         err := FSRead(PictF, howBig, PictBuffer);
  1332.                         fitsInPictBuffer := true;
  1333.                     end
  1334.                 else
  1335.                     fitsInPictBuffer := false;
  1336.                 if ((LutMode = custom) or (LutMode = CustomGrayscale)) and (not OptionKeyDown) then
  1337.                     GetClutFromPict(thePict);
  1338.                 if isGrayScaleClut then
  1339.                     ResetGrayMap;
  1340.                 GetPort(tPort);
  1341.                 SetPort(GrafPtr(osPort));
  1342.                 osPort^.fgColor := BlackC;
  1343.                 osPort^.bkColor := WhiteC;
  1344.                 EraseRect(PicRect);
  1345.                 SaveProcsPtr := pointer(osPort^.grafProcs);
  1346.                 SetStdCProcs(tempProcs);
  1347.                 tempProcs.getPicProc := @GetPICTData;
  1348.                 osPort^.grafProcs := @TempProcs;
  1349.                 err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  1350.                 FillPictBuffer;
  1351.                 if RestoringOutline then
  1352.                     RestoreOutline(thePict, PicRect)
  1353.                 else
  1354.                     DrawPicture(thePict, PicRect);
  1355.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  1356.                 osPort^.fgColor := ForegroundColor;
  1357.                 osPort^.bkColor := BackgroundColor;
  1358.                 DisposHandle(handle(thePict));
  1359.                 DisposPtr(PictBuffer);
  1360.                 SetPort(tPort);
  1361.                 vref := vnum;
  1362.                 PictureType := PictFile;
  1363.             end; {with}
  1364.         err := fsclose(PictF);
  1365.         SetupUndo;
  1366.         OpenPict := true;
  1367.     end;
  1368.  
  1369.  
  1370.     procedure SavePalette;
  1371.         var
  1372.             err: integer;
  1373.             where: Point;
  1374.             reply: SFReply;
  1375.             TheInfo: FInfo;
  1376.             PaletteData: array[1..4] of ColorArray;
  1377.             i, f: integer;
  1378.             ByteCount: LongInt;
  1379.     begin
  1380.         if info^.LUTMode <> ColorPalette then begin
  1381.                 PutMessage('You can only save pseudocolor palettes consisting of 32 or fewer colors.', '', '');
  1382.                 exit(SavePalette)
  1383.             end;
  1384.         where.v := 50;
  1385.         where.h := 50;
  1386.         SFPutFile(Where, 'Save Palette as?', PaletteName, nil, reply);
  1387.         if not reply.good then
  1388.             exit(SavePalette);
  1389.         err := GetFInfo(reply.fname, reply.vRefNum, TheInfo);
  1390.         case err of
  1391.             NoErr: 
  1392.                 if TheInfo.fdType <> 'ICOL' then begin
  1393.                         TypeMismatch(reply.fname);
  1394.                         exit(SavePalette)
  1395.                     end;
  1396.             FNFerr: 
  1397.                 begin
  1398.                     err := create(reply.fname, reply.vRefNum, 'IMAG', 'ICOL');
  1399.                     if IOCheck(err) <> 0 then
  1400.                         exit(SavePalette);
  1401.                 end;
  1402.             otherwise
  1403.                 if IOCheck(err) <> 0 then
  1404.                     exit(SavePalette);
  1405.         end;
  1406.         with info^ do begin
  1407.                 PaletteData[1, 0] := ncolors;
  1408.                 PaletteData[1, 1] := ColorStart;
  1409.                 PaletteData[1, 2] := ColorWidth;
  1410.                 for i := 3 to MaxPseudoColorsLessOne do
  1411.                     PaletteData[1, i] := 0;
  1412.                 for i := 0 to MaxPseudoColorsLessOne do begin
  1413.                         PaletteData[2, i] := BSR(RedX[i], 8);
  1414.                         PaletteData[3, i] := BSR(GreenX[i], 8);
  1415.                         PaletteData[4, i] := BSR(BlueX[i], 8);
  1416.                     end;
  1417.             end;
  1418.         with reply do begin
  1419.                 err := fsopen(fname, vRefNum, f);
  1420.                 if IOCheck(err) <> 0 then
  1421.                     exit(SavePalette);
  1422.                 err := SetFPos(f, FSFromStart, 0);
  1423.                 ByteCount := MaxPseudoColors * 4;
  1424.                 err := fswrite(f, ByteCount, @PaletteData);
  1425.                 if IOCheck(err) <> 0 then begin
  1426.                         err := fsclose(f);
  1427.                         err := FSDelete(fname, vRefNum);
  1428.                         exit(SavePalette)
  1429.                     end;
  1430.                 err := fsclose(f);
  1431.                 err := FlushVol(nil, vRefNum);
  1432.             end;
  1433.     end;
  1434.  
  1435.  
  1436.     procedure LoadPseudoColorPalette (fname: str255; vRefNum: integer);
  1437.     begin
  1438.         InitColor(fname, vRefNum);
  1439.         UpdateColors;
  1440.     end;
  1441.  
  1442.  
  1443.     procedure LoadPalette (FileType: OSType; fname: str255; vnum: integer);
  1444.         var
  1445.             RefNum: integer;
  1446.             ok: boolean;
  1447.             err: OSErr;
  1448.     begin
  1449.         err := SetVol(nil, vnum);
  1450.         refNum := OpenResFile(fname);
  1451.         if RefNum <> -1 then begin
  1452.                 if FileType = 'CLUT' then
  1453.                     ok := LoadClutResource(KlutzID)
  1454.                 else
  1455.                     ok := LoadClutResource(PixelPaintID);
  1456.                 CloseResFile(RefNum);
  1457.                 if isGrayScaleCLUT then begin
  1458.                         info^.LutMode := CustomGrayScale;
  1459.                         DrawGrayMap;
  1460.                     end;
  1461.             end;
  1462.     end;
  1463.  
  1464.  
  1465.     procedure GetFile;
  1466.         var
  1467.             where: Point;
  1468.             reply: SFReply;
  1469.             b: boolean;
  1470.             NumTypes, vnum: integer;
  1471.             sfPtr: ^SFTypeList;
  1472.             TypeList: array[0..5] of OSType;
  1473.     begin
  1474.         KillOperation;
  1475.         StopThresholding;
  1476.         where.v := 50;
  1477.         where.h := 50;
  1478.         typeList[0] := 'IPIC';
  1479.         typeList[1] := 'PICT';
  1480.         typeList[2] := 'TIFF';
  1481.         typeList[3] := 'ICOL';
  1482.         typeList[4] := 'PX05'; {PixelPaint LUT}
  1483.         typeList[5] := 'CLUT';  {Klutz LUT}
  1484.         sfPtr := @TypeList;
  1485.         if OptionKeyDown or ShiftKeyDown then
  1486.             NumTypes := -1 {Show all files}
  1487.         else
  1488.             NumTypes := 6;
  1489.         SFGetFile(Where, '', nil, NumTypes, sfPtr^, nil, reply);
  1490.         if reply.good then
  1491.             with reply do begin
  1492.                     vnum := vRefNum;
  1493.                     if ftype = 'IPIC' then begin
  1494.                             WhatToOpen := OpenImage;
  1495.                             OpenFile(fname, vNum)
  1496.                         end
  1497.                     else if ftype = 'PICT' then begin
  1498.                             b := OpenPICT(fname, vNum, false)
  1499.                         end
  1500.                     else if ftype = 'TIFF' then begin
  1501.                             WhatToOpen := OpenTIFF;
  1502.                             OpenFile(fname, vNum)
  1503.                         end
  1504.                     else if reply.ftype = 'ICOL' then
  1505.                         LoadPseudoColorPalette(fname, vNum)
  1506.                     else if reply.ftype = 'PX05' then
  1507.                         LoadPalette('PX05', fname, vNum)
  1508.                     else if reply.ftype = 'CLUT' then
  1509.                         LoadPalette('CLUT', fname, vNum)
  1510.                     else begin
  1511.                             WhatToOpen := OpenUnknown;
  1512.                             OpenFile(fname, vNum)
  1513.                         end;
  1514.                     info^.ScaleToFitWindow := false;
  1515.                 end;
  1516.     end;
  1517.  
  1518.  
  1519.     procedure OpenImportedPalette (fname: str255; vnum: integer);
  1520.         var
  1521.             err: OSErr;
  1522.             f, i: integer;
  1523.             ByteCount: LongInt;
  1524.             ImportedPalette: array[1..3] of packed array[0..255] of byte;
  1525.     begin
  1526.         StopThresholding;
  1527.         err := fsopen(fname, vNum, f);
  1528.         ByteCount := 768;
  1529.         err := fsRead(f, ByteCount, @ImportedPalette);
  1530.         if err = NoErr then
  1531.             with info^ do begin
  1532.                     for i := 0 to 255 do
  1533.                         with cTable[i], cTable[i].rgb do begin
  1534.                                 value := 0;
  1535.                                 red := bsl(ImportedPalette[1, i], 8);
  1536.                                 green := bsl(ImportedPalette[2, i], 8);
  1537.                                 blue := bsl(ImportedPalette[3, i], 8);
  1538.                             end;
  1539.                     LoadLUT(cTable);
  1540.                     LUTMode := Custom;
  1541.                     IdentityFunction := false;
  1542.                     if isGrayScaleCLUT then begin
  1543.                             info^.LutMode := CustomGrayScale;
  1544.                             DrawGrayMap;
  1545.                         end;
  1546.                 end
  1547.         else
  1548.             beep;
  1549.         err := fsClose(f);
  1550.     end;
  1551.  
  1552.  
  1553.     function FindWhatToImport: boolean;
  1554.         const
  1555.             TiffID = 3;
  1556.             McidID = 4;
  1557.             CustomID = 5;
  1558.             WidthID = 9;
  1559.             HeightID = 10;
  1560.             OffsetID = 11;
  1561.             PaletteID = 12;
  1562.         var
  1563.             mylog: DialogPtr;
  1564.             item, i: integer;
  1565.             SaveWhatToImport: WhatToImportType;
  1566.             SaveWidth, SaveHeight: integer;
  1567.             SaveOffset: LongInt;
  1568.  
  1569.         procedure SetRadioButton;
  1570.             var
  1571.                 i: integer;
  1572.         begin
  1573.             SetDialogItem(mylog, TiffID, 0);
  1574.             SetDialogItem(mylog, McidID, 0);
  1575.             SetDialogItem(mylog, PaletteID, 0);
  1576.             SetDialogItem(mylog, CustomID, 0);
  1577.             case WhatToImport of
  1578.                 ImportTiff: 
  1579.                     SetDialogItem(mylog, TiffID, 1);
  1580.                 ImportMcid: 
  1581.                     SetDialogItem(mylog, McidID, 1);
  1582.                 ImportPalette: 
  1583.                     SetDialogItem(mylog, PaletteID, 1);
  1584.                 ImportCustom: 
  1585.                     SetDialogItem(mylog, CustomID, 1);
  1586.             end;
  1587.         end;
  1588.  
  1589.     begin
  1590.         InitCursor;
  1591.         SaveWhatToImport := WhatToImport;
  1592.         SaveWidth := ImportCustomWidth;
  1593.         SaveHeight := ImportCustomHeight;
  1594.         SaveOffset := ImportCustomOffset;
  1595.         mylog := GetNewDialog(7000, nil, pointer(-1));
  1596.         SetRadioButton;
  1597.         SetDNum(MyLog, WidthID, ImportCustomWidth);
  1598.         SelIText(MyLog, WidthID, 0, 32767);
  1599.         SetDNum(MyLog, HeightID, ImportCustomHeight);
  1600.         SetDNum(MyLog, OffsetID, ImportCustomOffset);
  1601.         OutlineButton(MyLog, ok, 16);
  1602.         repeat
  1603.             ModalDialog(nil, item);
  1604.             if ((item >= TiffID) and (item <= CustomID)) or (item = PaletteID) then begin
  1605.                     case item of
  1606.                         TiffID: 
  1607.                             WhatToImport := ImportTiff;
  1608.                         McidID: 
  1609.                             WhatToImport := ImportMCID;
  1610.                         PaletteID: 
  1611.                             WhatToImport := ImportPalette;
  1612.                         CustomID: 
  1613.                             WhatToImport := ImportCustom;
  1614.                     end;
  1615.                     SetRadioButton;
  1616.                 end;
  1617.             if item = WidthID then begin
  1618.                     ImportCustomWidth := GetDNum(MyLog, WidthID);
  1619.                     if (ImportCustomWidth < 0) or (ImportCustomWidth > 2048) then begin
  1620.                             ImportCustomWidth := SaveWidth;
  1621.                             SetDNum(MyLog, WidthID, ImportCustomWidth);
  1622.                         end;
  1623.                     WhatToImport := ImportCustom;
  1624.                     SetRadioButton;
  1625.                 end;
  1626.             if item = HeightID then begin
  1627.                     ImportCustomHeight := GetDNum(MyLog, HeightID);
  1628.                     if (ImportCustomHeight < 0) or (ImportCustomHeight > 2048) then begin
  1629.                             ImportCustomHeight := SaveHeight;
  1630.                             SetDNum(MyLog, HeightID, ImportCustomHeight);
  1631.                         end;
  1632.                     WhatToImport := ImportCustom;
  1633.                     SetRadioButton;
  1634.                 end;
  1635.             if item = OffsetID then begin
  1636.                     ImportCustomOffset := GetDNum(MyLog, OffsetID);
  1637.                     if ImportCustomOffset < 0 then begin
  1638.                             ImportCustomOffset := SaveWidth;
  1639.                             SetDNum(MyLog, OffsetID, ImportCustomOffset);
  1640.                         end;
  1641.                     WhatToImport := ImportCustom;
  1642.                     SetRadioButton;
  1643.                 end;
  1644.         until (item = ok) or (item = cancel);
  1645.         DisposDialog(mylog);
  1646.         if item = cancel then begin
  1647.                 WhatToImport := SaveWhatToImport;
  1648.                 ImportCustomWidth := SaveWidth;
  1649.                 ImportCustomHeight := SaveHeight;
  1650.                 ImportCustomOffset := SaveOffset;
  1651.                 FindWhatToImport := false
  1652.             end
  1653.         else
  1654.             FindWhatToImport := true;
  1655.     end;
  1656.  
  1657.  
  1658.     procedure ImportFile;
  1659.         var
  1660.             where: Point;
  1661.             typeList: SFTypeList;
  1662.             reply: SFReply;
  1663.     begin
  1664.         StopThresholding;
  1665.         if FindWhatToImport then begin
  1666.                 where.v := 50;
  1667.                 where.h := 50;
  1668.                 SFGetFile(Where, '', nil, -1, typeList, nil, reply); {Show User all Types}
  1669.                 if reply.good then begin
  1670.                         case WhatToImport of
  1671.                             ImportTiff: 
  1672.                                 WhatToOpen := OpenTiff;
  1673.                             ImportMCID: 
  1674.                                 WhatToOpen := OpenImported;
  1675.                             ImportPalette: 
  1676.                                 OpenImportedPalette(reply.fname, reply.vRefNum);
  1677.                             ImportCustom: 
  1678.                                 WhatToOpen := OpenCustom;
  1679.                         end;
  1680.                         if WhatToImport <> ImportPalette then
  1681.                             OpenFile(reply.fname, reply.vRefNum);
  1682.                     end;
  1683.             end;
  1684.     end;
  1685.  
  1686.  
  1687.     procedure RevertToSaved;
  1688.         var
  1689.             fname: str255;
  1690.             err, f: integer;
  1691.             ok: boolean;
  1692.     begin
  1693.         if Info = NoInfo then begin
  1694.                 beep;
  1695.                 exit(RevertToSaved)
  1696.             end;
  1697.         if OpPending then
  1698.             KillRoi;
  1699.         StopThresholding;
  1700.         with Info^ do begin
  1701.                 GetWTitle(wptr, fname);
  1702.                 if PictureType = PICTFile then begin
  1703.                         ok := OpenPICT(fname, vref, true);
  1704.                         invalRect(wrect)
  1705.                     end
  1706.                 else begin
  1707.                         ShowWatch;
  1708.                         err := fsopen(fname, vref, f);
  1709.                         ok := true;
  1710.                         if HeaderOffset <> -1 then
  1711.                             ok := OpenImageHeader(f, fname, vref);
  1712.                         if ok then begin
  1713.                                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  1714.                                 err := fsread(f, PicSize, PicBaseAddr);
  1715.                                 with info^ do
  1716.                                     if (PictureType = PDP11) or (PictureType = InvertedTIFF) then
  1717.                                         InvertPic;
  1718.                                 InvalRect(wrect);
  1719.                             end;
  1720.                         err := fsclose(f);
  1721.                         RoiShowing := false;
  1722.                     end;
  1723.                 OpPending := false;
  1724.                 Changes := false;
  1725.             end; {with}
  1726.     end;
  1727.  
  1728.  
  1729.     procedure SaveSettings;
  1730.         var
  1731.             size: LongInt;
  1732.             TempH: handle;
  1733.             SettingsH: handle;
  1734.     begin
  1735.         with settings, info^ do begin
  1736.                 sForegroundColor := ForegroundColor;
  1737.                 sBackgroundColor := BackgroundColor;
  1738.                 sBrushHeight := BrushHeight;
  1739.                 sBrushWidth := BrushWidth;
  1740.                 sAirbrushDiameter := AirbrushDiameter;
  1741.                 sLUTMode := LUTMode;
  1742.                 sColorStart := ColorStart;
  1743.                 sColorWidth := ColorWidth;
  1744.                 sCurrentFontID := CurrentFontID;
  1745.                 sCurrentStyle := CurrentStyle;
  1746.                 sCurrentSize := CurrentSize;
  1747.                 sTextJust := TextJust;
  1748.                 sTextBack := TextBack;
  1749.                 sNExtraColors := nExtraColors;
  1750.                 sExtraColors := ExtraColors;
  1751.                 sInvertVideo := InvertVideo;
  1752.                 sMeasurements := Measurements;
  1753.                 sInvertPlots := InvertPlots;
  1754.                 sAutoScalePlots := AutoScalePlots;
  1755.                 sLinePlot := LinePlot;
  1756.                 sDrawPlotLabels := DrawPlotLabels;
  1757.                 sProfilePlotMin := ProfilePlotMin;
  1758.                 sProfilePlotMax := ProfilePlotMax;
  1759.                 sFixedSizePlot := FixedSizePlot;
  1760.                 sProfilePlotWidth := ProfilePlotWidth;
  1761.                 sProfilePlotHeight := ProfilePlotHeight;
  1762.                 snFrames := nFrames;
  1763.                 sNewPicWidth := NewPicWidth;
  1764.                 sNewPicHeight := NewPicHeight;
  1765.                 sBufferSize := BufferSize;
  1766.                 sMaxScionWidth := MaxScionWidth;
  1767.                 sThresholdToForeground := ThresholdToForeground;
  1768.                 sNonThresholdToBackground := NonThresholdToBackground;
  1769.                 sVideoChannel := VideoChannel;
  1770.                 sWhatToImport := WhatToImport;
  1771.                 sImportCustomWidth := ImportCustomWidth;
  1772.                 sImportCustomHeight := ImportCustomHeight;
  1773.                 sImportCustomOffset := ImportCustomOffset;
  1774.                 sWandAutoMeasure := WandAutoMeasure;
  1775.                 sWandAutoNumber := WandAutoNumber;
  1776.             end;
  1777.         SettingsH := GetResource('SETT', 1000);
  1778.         if GetHandleSize(SettingsH) > 0 then
  1779.             RmveResource(SettingsH);
  1780.         size := SizeOF(settings);
  1781.         TempH := NewHandle(size);
  1782.         BlockMove(@settings, TempH^, size);
  1783.         AddResource(TempH, 'SETT', 1000, '');
  1784.         WriteResource(TempH);
  1785.         if ResError <> NoErr then
  1786.             SysBeep(1);
  1787.         DisposHandle(TempH);
  1788.     end;
  1789.  
  1790.  
  1791.     procedure PrintErrCheck;
  1792.         var
  1793.             err: integer;
  1794.             ticks: LongInt;
  1795.     begin
  1796.         err := PrError;
  1797.         if err < 0 then
  1798.             beep;
  1799.     end;
  1800.  
  1801.  
  1802.     procedure DoPageSetup;
  1803.         var
  1804.             result: boolean;
  1805.     begin
  1806.         if PrintRecord = nil then begin
  1807.                 PrintRecord := THPrint(NewHandle(SizeOF(TPrint)));
  1808.                 PrintDefault(PrintRecord);
  1809.             end;
  1810.         PrOpen;
  1811.         if PrError = NoErr then begin
  1812.                 result := PrValidate(PrintRecord);
  1813.                 result := PrStlDialog(PrintRecord);
  1814.             end;
  1815.         PrClose;
  1816.     end;
  1817.  
  1818.  
  1819.     procedure PrintHalftone;
  1820.         const
  1821.             PostScriptBegin = 190;
  1822.             PostScriptEnd = 191;
  1823.             PostScriptHandle = 192;
  1824.             TextIsPostScript = 194;
  1825.         var
  1826.             HexBufH: handle;
  1827.             hloc, vloc, HexCount, iheight, iwidth, hstart, vstart: integer;
  1828.             Height, Width, eof, angle, freq: str255;
  1829.             aLine: LineType;
  1830.             HexBuf: packed array[0..4200] of char;
  1831.             err: OSErr;
  1832.             table: LookupTable;
  1833.  
  1834.         procedure PutHEX (byt: integer);
  1835.             var
  1836.                 i, LowByte, HighByte, tmp: integer;
  1837.                 h: char;
  1838.         begin
  1839.             if not IdentityFunction then
  1840.                 byt := table[byt];
  1841.             byt := 255 - byt;
  1842.             LowByte := byt mod 16;
  1843.             byt := byt div 16;
  1844.             HighByte := byt mod 16;
  1845.             for i := 1 to 2 do begin
  1846.                     if i = 1 then
  1847.                         tmp := HighByte
  1848.                     else
  1849.                         tmp := LowByte;
  1850.                     case tmp of
  1851.                         0: 
  1852.                             h := '0';
  1853.                         1: 
  1854.                             h := '1';
  1855.                         2: 
  1856.                             h := '2';
  1857.                         3: 
  1858.                             h := '3';
  1859.                         4: 
  1860.                             h := '4';
  1861.                         5: 
  1862.                             h := '5';
  1863.                         6: 
  1864.                             h := '6';
  1865.                         7: 
  1866.                             h := '7';
  1867.                         8: 
  1868.                             h := '8';
  1869.                         9: 
  1870.                             h := '9';
  1871.                         10: 
  1872.                             h := 'a';
  1873.                         11: 
  1874.                             h := 'b';
  1875.                         12: 
  1876.                             h := 'c';
  1877.                         13: 
  1878.                             h := 'd';
  1879.                         14: 
  1880.                             h := 'e';
  1881.                         15: 
  1882.                             h := 'f';
  1883.                     end;
  1884.                     hexbuf[HexCount] := h;
  1885.                     HexCount := HexCount + 1;
  1886.                     if HexCount mod 80 = 0 then begin
  1887.                             HexBuf[HexCount] := return;
  1888.                             HexCount := HexCount + 1
  1889.                         end;
  1890.                 end;
  1891.         end;
  1892.  
  1893.     begin
  1894.         if not IdentityFunction then
  1895.             GetLookupTable(table);
  1896.         MoveTo(-1, -1);
  1897.         LineTo(-1, -1); {Nothing prints without this dummy dot!}
  1898.         with info^ do begin
  1899.                 PicComment(PostScriptBegin, 0, nil); {See Tech Note #91}
  1900.                 PicComment(TextIsPostScript, 0, nil);
  1901.                 NumToString(HalftoneFrequency, freq);
  1902.                 NumToString(HalftoneAngle, angle);
  1903.                 if HalftoneDotFunction then
  1904.                     DrawString(concat(freq, ' ', angle, ' {dup mul exch dup mul add 1 exch sub} setscreen'))
  1905.                 else
  1906.                     DrawString(concat(freq, ' ', angle, ' {pop} setscreen'));
  1907.                 DrawString('0 0 translate');
  1908.                 with osRoiRect do begin
  1909.                         iwidth := right - left;
  1910.                         iheight := bottom - top;
  1911.                         hstart := left;
  1912.                         vstart := top;
  1913.                     end;
  1914.                 NumToString(iwidth, width);
  1915.                 NumToString(iheight, height);
  1916.                 DrawString(concat(width, ' ', height, ' scale'));
  1917.                 DrawString(concat('/PicStr ', width, ' string def'));
  1918.                 DrawString(concat(width, ' ', height, ' 8 [', width, ' 0 0 ', height, ' 0 0]'));
  1919.                 DrawString('{currentfile PicStr readhexstring pop} image');
  1920.                 for vloc := vstart to vstart + iheight - 1 do begin
  1921.                         GetLine(hstart, vloc, iwidth, aline);
  1922.                         HexCount := 0;
  1923.                         for hloc := 0 to iwidth - 1 do
  1924.                             PutHex(aline[hloc]);
  1925.                         HexBuf[HexCount] := return;
  1926.                         HexCount := HexCount + 1;
  1927.                         err := PtrToHand(@HexBuf, HexBufH, HexCount);
  1928.                         if err <> noErr then
  1929.                             exit(PrintHalftone);
  1930.                         PicComment(PostScriptHandle, HexCount, HexBufH);
  1931.                         DisposHandle(HexBufH);
  1932.                         Show2Values(vloc - vstart, iheight);
  1933.                         if CommandPeriod then begin
  1934.                                 beep;
  1935.                                 eof := chr(4);
  1936.                                 DrawString(eof);
  1937.                                 exit(PrintHalftone)
  1938.                             end;
  1939.                     end;
  1940.             end;
  1941.     end;
  1942.  
  1943.  
  1944.     procedure PrintPicture (OptionKeyWasDown: boolean; PageWidth, PageHeight: integer);
  1945.         var
  1946.             PrintRect: rect;
  1947.             Width, Height: integer;
  1948.     begin
  1949.         if isLaserWriter and (not OptionKeyDown) and (not OptionKeyWasDown) then
  1950.             PrintHalftone
  1951.         else
  1952.             with info^ do begin
  1953.                     LoadLUT(cTable);
  1954.                     hlock(handle(osPort^.portPixMap));
  1955.                     if BitAnd(thePort^.portBits.rowBytes, $8000) = $8000 then begin
  1956.         {Assume driver understands Color QD}
  1957.                             with osroiRect do begin
  1958.                                     width := right - left;
  1959.                                     height := bottom - top;
  1960.                                 end;
  1961.                             with PrintRect do begin
  1962.                                     left := 0;
  1963.                                     top := 0;
  1964.                                     if width < PageWidth then
  1965.                                         left := (PageWidth - width) div 2;
  1966.                                     if height < PageHeight then
  1967.                                         top := (Pageheight - height) div 2;
  1968.                                     right := left + width;
  1969.                                     bottom := top + height;
  1970.                                 end;
  1971.                             hlock(handle(CGrafPort(ThePort^).PortPixMap));
  1972.                             CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(CGrafPort(ThePort^).PortPixMap)^^, osroiRect, PrintRect, SrcCopy, nil);
  1973.                             hunlock(handle(CGrafPort(ThePort^).PortPixMap))
  1974.                         end
  1975.                     else
  1976.                         CopyBits(BitMapHandle(osPort^.portPixMap)^^, thePort^.PortBits, osRoiRect, osroiRect, SrcCopy, nil);
  1977.                     hunlock(handle(osPort^.portPixMap));
  1978.                 end;
  1979.     end;
  1980.  
  1981.  
  1982.     procedure PrintResults (PageHeight: integer; var PrintPort: TPPrPort);
  1983.         const
  1984.             LinesPerPage = 59;
  1985.             MaxLine = 100;
  1986.         var
  1987.             LineInc, hloc, vloc, i, LineCount, CharCount: integer;
  1988.             aLine: str255;
  1989.     begin
  1990.         CopyResultsToBuffer;
  1991.         TextOnClip := false;
  1992.         LineInc := PageHeight div LinesPerPage;
  1993.         hloc := 0;
  1994.         vloc := LineInc;
  1995.         LineCount := 0;
  1996.         CharCount := 0;
  1997.         TextFont(Monaco);
  1998.         TextSize(9);
  1999.         i := 1;
  2000.         repeat
  2001.             while TextBufP^[i] >= ' ' do begin
  2002.                     CharCount := CharCount + 1;
  2003.                     aLine[CharCount] := TextBufP^[i];
  2004.                     i := i + 1;
  2005.                 end;
  2006.             aLine[0] := chr(CharCount);
  2007.             MoveTo(hloc, vloc);
  2008.             DrawString(aLine);
  2009.             CharCount := 0;
  2010.             if TextBufP^[i] = return then begin
  2011.                     vLoc := vLoc + LineInc;
  2012.                     hloc := 0;
  2013.                     LineCount := LineCount + 1;
  2014.                     if LineCount >= LinesPerPage then begin
  2015.                             LineCount := 0;
  2016.                             if i < TextBufSize then begin
  2017.                                     PrClosePage(PrintPort);
  2018.                                     PrintErrCheck;
  2019.                                     PrOpenPage(PrintPort, nil);
  2020.                                     vloc := LineInc
  2021.                                 end;
  2022.                         end;
  2023.                 end;
  2024.             i := i + 1;
  2025.         until i > TextBufSize;
  2026.     end;
  2027.  
  2028.  
  2029.     procedure Print (ShowDialog: boolean);
  2030.         var
  2031.             err, i, LinesToPrint: Integer;
  2032.             tPort: GrafPtr;
  2033.             PrintPort: TPPrPort;
  2034.             PrintStatusRec: TPrStatus;
  2035.             prect: rect;
  2036.             result, OptionKeyWasDown: boolean;
  2037.     begin
  2038.         OptionKeyWasDown := OptionKeyDown;
  2039.         ValuesMode := CountValues;
  2040.         DrawLabels;
  2041.         if WhatToPrint = PrintImage then
  2042.             SelectAll(false);
  2043.         if (WhatToPrint = PrintImage) or (WhatToPrint = PrintSelection) then begin
  2044.                 if OpPending then
  2045.                     KillRoi;
  2046.                 with info^.osroiRect do
  2047.                     LinesToPrint := bottom - top;
  2048.                 Show2Values(0, LinesToPrint);
  2049.             end;
  2050.         GetPort(tPort);
  2051.         if PrintRecord = nil then begin
  2052.                 PrintRecord := THPrint(NewHandle(SizeOF(TPrint)));
  2053.                 PrintDefault(PrintRecord);
  2054.             end;
  2055.         PrOpen;
  2056.         if PrError = NoErr then begin
  2057.                 result := PrValidate(PrintRecord);
  2058.                 isLaserWriter := BSR(PrintRecord^^.prStl.wDev, 8) = 3;
  2059.                 prect := PrintRecord^^.prInfo.rPage;
  2060.                 if ShowDialog then
  2061.                     result := PrJobDialog(PrintRecord)
  2062.                 else
  2063.                     result := true;
  2064.                 SetCursor(watch^^);
  2065.                 if result then
  2066.                     for i := 1 to PrintRecord^^.PrJob.icopies do begin
  2067.                             PrintPort := PrOpenDoc(PrintRecord, nil, nil);
  2068.                             PrintErrCheck;
  2069.                             Printing := true;
  2070.                             PrOpenPage(PrintPort, nil);
  2071.                             if PrError = NoErr then
  2072.                                 case WhatToPrint of
  2073.                                     PrintImage, PrintSelection: 
  2074.                                         PrintPicture(OptionKeyWasDown, prect.right, prect.bottom);
  2075.                                     PrintAreas, PrintLengths, PrintPoints: 
  2076.                                         PrintResults(prect.Bottom, PrintPort);
  2077.                                     PrintPlot: 
  2078.                                         DrawPlot;
  2079.                                     PrintHistogram: 
  2080.                                         DrawHistogram;
  2081.                                 end;
  2082.                             Printing := false;
  2083.                             PrClosePage(PrintPort);
  2084.                             PrintErrCheck;
  2085.                             PrCloseDoc(PrintPort);
  2086.                             PrintErrCheck;
  2087.                             if PrintRecord^^.prJob.bJDocLoop = bSpoolLoop then
  2088.                                 PrPicFile(PrintRecord, nil, nil, nil, PrintStatusRec);
  2089.                         end;
  2090.             end;
  2091.         PrClose;
  2092.         SetPort(tPort);
  2093.         if WhatToPrint = PrintImage then
  2094.             KillRoi;
  2095.     end;
  2096.  
  2097.  
  2098.     procedure SetHalftone;
  2099.         const
  2100.             FrequencyID = 11;
  2101.             FirstAngleID = 3;
  2102.             LastAngleID = 5;
  2103.         var
  2104.             mylog: DialogPtr;
  2105.             item, i, ignore, SaveFrequency, SaveAngle, AngleID: integer;
  2106.             SaveFunction: boolean;
  2107.             str: str255;
  2108.     begin
  2109.         SaveFrequency := HalftoneFrequency;
  2110.         SaveAngle := HalftoneAngle;
  2111.         SaveFunction := HalftoneDotFunction;
  2112.         mylog := GetNewDialog(30, nil, pointer(-1));
  2113.         SetDNum(MyLog, FrequencyID, HalftoneFrequency);
  2114.         SelIText(MyLog, FrequencyID, 0, 32767);
  2115.         OutlineButton(MyLog, ok, 16);
  2116.         if HalftoneAngle = 45 then
  2117.             AngleID := FirstAngleID
  2118.         else if HalftoneAngle = 90 then
  2119.             AngleID := FirstAngleID + 1
  2120.         else if HalftoneAngle = 0 then
  2121.             AngleID := FirstAngleID + 2;
  2122.         SetDialogItem(mylog, AngleID, 1);
  2123.         if HalftoneDotFunction then
  2124.             SetDialogItem(mylog, 7, 1)
  2125.         else
  2126.             SetDialogItem(mylog, 8, 1);
  2127.         repeat
  2128.             ModalDialog(nil, item);
  2129.             if item = FrequencyID then
  2130.                 HalftoneFrequency := GetDNum(MyLog, FrequencyID);
  2131.             if (item >= FirstAngleID) and (item <= LastAngleID) then begin
  2132.                     for i := FirstAngleID to LastAngleID do
  2133.                         SetDialogItem(mylog, i, 0);
  2134.                     SetDialogItem(mylog, item, 1);
  2135.                     AngleID := item;
  2136.                     case AngleID of
  2137.                         3: 
  2138.                             HalftoneAngle := 45;
  2139.                         4: 
  2140.                             HalftoneAngle := 90;
  2141.                         5: 
  2142.                             HalftoneAngle := 0;
  2143.                     end;
  2144.                 end;
  2145.             if (item >= 7) and (item <= 8) then begin
  2146.                     for i := 7 to 8 do
  2147.                         SetDialogItem(mylog, i, 0);
  2148.                     SetDialogItem(mylog, item, 1);
  2149.                     HalftoneDotFunction := item = 7;
  2150.                 end;
  2151.         until (item = ok) or (item = cancel);
  2152.         DisposDialog(mylog);
  2153.         if item = cancel then begin
  2154.                 HalftoneFrequency := SaveFrequency;
  2155.                 HalftoneAngle := SaveAngle;
  2156.                 HalftoneDotFunction := SaveFunction;
  2157.             end;
  2158.     end;
  2159.  
  2160.     procedure GetFileInfo (name: str255; vnum: integer; var DateCreated, LastModified: str255);
  2161.         var
  2162.             FileParmBlock: ParmBlkPtr;
  2163.             theErr: OSErr;
  2164.             DateVar, TimeVar: str255;
  2165.             Secs: LongInt;
  2166.     begin
  2167.         DateCreated := '';
  2168.         new(FIleParmBlock);
  2169.         if FileParmBlock <> nil then
  2170.             with FileParmBlock^ do begin
  2171.                     ioCompletion := nil;
  2172.                     ioNamePtr := @name;
  2173.                     ioVRefNum := vnum;
  2174.                     ioFVersNum := 0;
  2175.                     ioFDirIndex := 0;
  2176.                     theErr := PBGetFInfo(FileParmBlock, false);
  2177.                     if theErr = NoErr then begin
  2178.                             Secs := ioFlCrDat;
  2179.                             IUDateString(Secs, abbrevDate, DateVar);
  2180.                             IUTimeString(Secs, true, TimeVar);
  2181.                             DateCreated := concat(DateVar, '  ', TimeVar);
  2182.                             Secs := ioFlMDDat;
  2183.                             IUDateString(Secs, abbrevDate, DateVar);
  2184.                             IUTimeString(Secs, true, TimeVar);
  2185.                             LastModified := concat(DateVar, '  ', TimeVar);
  2186.                         end;
  2187.                     Dispose(FileParmBlock);
  2188.                 end;
  2189.     end;
  2190.  
  2191.  
  2192.     procedure GetVolumnInfo (vnum: integer; var VolumnName: str255; var FreeSpace: LongInt);
  2193.         var
  2194.             theErr: OSErr;
  2195.             SPtr: StringPtr;
  2196.             VolParmBlock: ParmBlkPtr;
  2197.     begin
  2198.         VolumnName := '';
  2199.         new(SPtr);
  2200.         new(VolParmBlock);
  2201.         if (SPtr <> nil) and (VolParmBlock <> nil) then
  2202.             with VolParmBlock^ do begin
  2203.                     SPtr^ := '';
  2204.                     ioVRefNum := vnum;
  2205.                     ioNamePtr := SPtr;
  2206.                     ioCompletion := nil;
  2207.                     ioVolIndex := -1;
  2208.                     theErr := PBGetVInfo(VolParmBlock, false);
  2209.                     VolumnName := ioNamePtr^;
  2210.                     FreeSpace := ioVAlBlkSiz * ioVFrBlk;
  2211.                     dispose(SPtr);
  2212.                     dispose(VolParmBlock);
  2213.                 end;
  2214.     end;
  2215.  
  2216.  
  2217.     procedure GetInfo;
  2218.         const
  2219.             InfoWindowWidth = 260;
  2220.             InfoWindowHeight = 300;
  2221.         var
  2222.             name, str, DateCreated, LastModified, VolumnName: str255;
  2223.             hloc, vloc: integer;
  2224.             tPort: GrafPtr;
  2225.             SaveRoiShowing: boolean;
  2226.             FreeSpace: LongInt;
  2227.             SaveForeIndex, SaveBackIndex: integer;
  2228.  
  2229.         procedure NewLine;
  2230.         begin
  2231.             vloc := vloc + 13;
  2232.             MoveTo(hloc, vloc);
  2233.         end;
  2234.  
  2235.         procedure NewParagraph;
  2236.         begin
  2237.             vloc := vloc + 18;
  2238.             MoveTo(hloc, vloc);
  2239.         end;
  2240.  
  2241.     begin
  2242.         name := concat('Info About ', info^.title);
  2243.         SaveRoiShowing := info^.RoiShowing;
  2244.         SaveForeIndex := ForegroundColor;
  2245.         SaveBackIndex := BackgroundColor;
  2246.         SetForegroundColor(BlackC);
  2247.         SetBackgroundColor(WhiteC);
  2248.         if NewPicWindow(name, InfoWindowWidth, InfoWindowHeight) then
  2249.             with SaveInfo^ do begin
  2250.                     hloc := 15;
  2251.                     vloc := 10;
  2252.                     GetPort(tPort);
  2253.                     SetPort(GrafPtr(info^.osPort));
  2254.                     TextFont(ApplFont);
  2255.                     TextSize(9);
  2256.                     NewLine;
  2257.                     DrawBString('Name: ');
  2258.                     DrawString(title);
  2259.                     NewParagraph;
  2260.                     DrawBString('Width: ');
  2261.                     DrawLong(PixelsPerLine);
  2262.                     NewLine;
  2263.                     DrawBString('Height: ');
  2264.                     DrawLong(nlines);
  2265.                     NewLine;
  2266.                     DrawBString('Size: ');
  2267.                     DrawLong(PicSize div 1024);
  2268.                     DrawString('K');
  2269.                     NewParagraph;
  2270.                     GetFileInfo(title, vref, DateCreated, LastModified); {DateCreated:='';}
  2271.                     if DateCreated <> '' then begin
  2272.                             DrawBString('Creation Date: ');
  2273.                             DrawString(DateCreated);
  2274.                             NewLine;
  2275.                             DrawBString('Last Modified: ');
  2276.                             DrawString(LastModified);
  2277.                             NewLine;
  2278.                         end;
  2279.                     GetVolumnInfo(vref, VolumnName, FreeSpace);
  2280.                     if VolumnName <> '' then begin
  2281.                             DrawBString('Volume: ');
  2282.                             DrawString(VolumnName);
  2283.                             DrawString(' (');
  2284.                             DrawLong(FreeSpace div 1024);
  2285.                             DrawString('K free)');
  2286.                             NewParagraph;
  2287.                         end;
  2288.                     DrawBString('Type: ');
  2289.                     case PictureType of
  2290.                         pdp11: 
  2291.                             str := 'PDP-11';
  2292.                         NewPicture: 
  2293.                             str := 'New';
  2294.                         normal: 
  2295.                             str := 'Normal';
  2296.                         PictFile: 
  2297.                             str := 'PICT';
  2298.                         TiffFile: 
  2299.                             str := 'TIFF';
  2300.                         InvertedTIFF: 
  2301.                             str := 'TIFF';
  2302.                         Leftover: 
  2303.                             str := 'Left Over';
  2304.                         imported: 
  2305.                             str := 'Imported';
  2306.                         camera: 
  2307.                             str := 'Camera(QuickCapture)';
  2308.                         BlankField: 
  2309.                             str := 'Blank Field';
  2310.                         ScionType: 
  2311.                             str := 'Camera(Scion)';
  2312.                         otherwise
  2313.                             ;
  2314.                     end;
  2315.                     if BinaryPic then
  2316.                         str := concat(str, ' (Binary)');
  2317.                     DrawString(str);
  2318.                     NewLine;
  2319.                     DrawBString('Lookup Table: ');
  2320.                     case LutMode of
  2321.                         ColorPalette: 
  2322.                             str := 'Pseudocolor';
  2323.                         AppleDefault: 
  2324.                             str := 'System';
  2325.                         Spectrum: 
  2326.                             str := 'Spectrum';
  2327.                         GrayScale: 
  2328.                             str := 'Grayscale';
  2329.                         Custom: 
  2330.                             str := 'Custom';
  2331.                         CustomGrayscale: 
  2332.                             str := 'Custom Grayscale';
  2333.                         otherwise
  2334.                     end;
  2335.                     DrawString(str);
  2336.                     NewLine;
  2337.                     DrawBString('Magnification: ');
  2338.                     if ScaleToFitWindow then begin
  2339.                             DrawReal(magnification, 1, 2);
  2340.                             DrawString(' (Scale to Window Mode)')
  2341.                         end
  2342.                     else begin
  2343.                             DrawReal(magnification, 1, 0);
  2344.                             DrawString(':1')
  2345.                         end;
  2346.                     NewLine;
  2347.                     DrawBString('Scale: ');
  2348.                     if scale <> 0.0 then begin
  2349.                             DrawReal(scale, 1, 3);
  2350.                             DrawString(' Pixels Per ');
  2351.                             DrawString(units)
  2352.                         end
  2353.                     else
  2354.                         DrawString('None');
  2355.                     if calibrated then begin
  2356.                             NewLine;
  2357.                             DrawBString('Unit of Measure:');
  2358.                             if UnitOfMEasure = '' then
  2359.                                 DrawString('None')
  2360.                             else
  2361.                                 DrawString(UnitOfMeasure)
  2362.                         end;
  2363.                     NewParagraph;
  2364.                     DrawBString('Free RAM: ');
  2365.                     DrawLong(FreeMem div 1024);
  2366.                     DrawString('K');
  2367.                     NewLine;
  2368.                     DrawBString('Largest Free Block: ');
  2369.                     DrawLong(MaxBlock div 1024);
  2370.                     DrawString('K');
  2371.                     NewParagraph;
  2372.                     if RoiType <> NoRoi then begin
  2373.                             DrawBString('Selection Type: ');
  2374.                             case RoiType of
  2375.                                 RgnRoi: 
  2376.                                     DrawString('Freehand or Polygon');
  2377.                                 RectRoi: 
  2378.                                     DrawString('Rectangle');
  2379.                                 OvalRoi: 
  2380.                                     DrawString('Oval');
  2381.                                 RoundRectRoi: 
  2382.                                     DrawString('Rounded Rectangle');
  2383.                             end;
  2384.                             NewLine;
  2385.                             with osroirect do begin
  2386.                                     DrawBString('    Location: ');
  2387.                                     DrawLong(left);
  2388.                                     DrawString(', ');
  2389.                                     DrawLong(PicRect.bottom - top - 1);
  2390.                                     NewLine;
  2391.                                     DrawBString('    Width: ');
  2392.                                     DrawLong(right - left);
  2393.                                     NewLine;
  2394.                                     DrawBString('    Height: ');
  2395.                                     DrawLong(bottom - top);
  2396.                                 end
  2397.                         end
  2398.                     else
  2399.                         DrawBString('No Selection');
  2400.                     SetPort(tPort);
  2401.                 end;
  2402.         SetForegroundColor(SaveForeIndex);
  2403.         SetBackgroundColor(SaveBackIndex);
  2404.     end;
  2405.  
  2406. end.